-- Radical by Basil Voronkov
-- Module 'util'
---------------------------------------------
-- Curried utility function that usually wrap 
-- standard INSTEAD functions and additional
-- extension functions. Curried functions usually
-- end with '_' postfix.
require "lib/core"

util = {}

function gt(x, y)
  return x>y;
end

function lt(x, y)
  return x<y;
end

function set_flag(var,flag)
  if flag then
    exec(var.."=true");
  else
    exec(var.."=false");
  end
end

function is_set(var)
  return apply(var);
end

function set(var)
  set_flag(var, true);
end

function unset(var)
  set_flag(var, false);
end

function loc(...)
  local hs = deref(here());
  for i,v in ipairs(arg) do
    if (is_table(v) and here() == v) or hs == v then
      return true;
    end
  end
end

function util.generic_choose(tab, fun)
  local df = nil;
  for i,v in pairs(tab) do
    if i == "default" then
      df = v;
    elseif fun(i) then
      return rcall(v);
    end
  end
  if df ~= nil then
    return rcall(df);
  else
    return nil;
  end
end

-- Curried functions
function refresh()
  walk(here());
end

function clstmp()
  here().tmpdsc=nil;
end

function refresh_(dsc)
  return function()
    here().tmpdsc = dsc;
    walk(here());
  end
end

function refreshblack()
  walkblack_(here())();
end

function walkif_(cnd,fst,snd)
  return function()
    if apply(cnd) then
      walk(fst);
    else
      walk(snd);
    end
  end
end

function walkifseen_(fst,snd)
  return function(s)
    if s._seen then
      walk(fst);
    else
      walk(snd);
    end
  end
end

function apply_(src)
  return function()
    return apply(src);
  end
end

function exec_(src)
  return function()
    return exec(src);
  end
end

function episode_(key)
  return function()
    episodes.unlock(key);
  end
end

function unlock_(key)
  return function()
    bonus.unlock(key);
  end
end

function take_(o)
  return function()
    inventory.add(o);
  end
end

function condition_(cond, res)
  return choose_ { [cond] = res };
end

function gamefile_(fl)
  return function()
    gamefile(const.path.game..fl, true);
  end
end

function sound_(snd)
  return function() 
    play_sound(snd);
  end
end

function music_(mus)
  return function() 
    play_music(mus);
  end
end

function musplayer_(nm)
  return function()
    ref(nm):activate();
    ref(nm):play();
  end
end

function drop_(s)
  return function()
    inventory.remove(s);
  end
end

function put_(o,s)
  return function()
    put(o,s);
  end
end

function walk_(loc,dsc)
  return function()
    here().showitem = nil;
    local o = ref(loc);
    if o ~= nil then
      o.tmpdsc = dsc;
    end
    walk(loc);
  end
end

function safewalk_(loc)
  return function()
    local hw = here();
    if hw.tilecache ~= nil then
      sprite.free(hw.tilecache);
      hw.tilecache = nil;
    end
    hw.showitem = nil;
    walk(loc);
  end
end

function walkblack_(loc,tmpdsc)
  return function()
    sys_blackroom._transfer = loc;
    sys_blackroom._transferdsc = tmpdsc;
    walk("sys_blackroom");
  end
end

function walkblack2_(loc,tmpdsc)
  return function()
    sys_blackroom2._transfer = loc;
    sys_blackroom2._transferdsc = tmpdsc;
    walk("sys_blackroom2");
  end
end

function walkblack3_(loc,tmpdsc)
  return function()
    sys_blackroom3._transfer = loc;
    sys_blackroom3._transferdsc = tmpdsc;
    walk("sys_blackroom3");
  end
end

function walkblack5_(loc,tmpdsc)
  return function()
    sys_blackroom4._transfer = loc;
    sys_blackroom4._transferdsc = tmpdsc;
    walk("sys_blackroom4");
  end
end

function set_(var)
  return function()
    set(var);
  end
end

function toggle_(var)
  return function()
    if apply(var) then
      unset(var);
    else
      set(var);
    end
  end
end

function inc_(var)
  return function()
    exec(var.."="..var.."+1");
  end
end

function unset_(var)
  return function()
    unset(var);
  end
end

function if_(c)
  return function()
    return is_set(c);
  end
end

function not_(c)
  return function()
    return not is_set(c);
  end
end

function choose_(tab)
  return function()
    return util.generic_choose(tab, apply);
  end
end

function select_(var)
  return function(tab)
    return function()
      return util.generic_choose(tab, function(a) return apply(var.."=="..a) end);
    end
  end
end

function location_(tab)
  return function()
    return util.generic_choose(tab, function(s) return loc(s) end);
  end
end

function for_(tab)
  return function()
    return util.generic_choose(tab, function(s) return _activeitem == s end);
  end
end

function chain_(tab)
  return function(s)
    local ret = nil;
    for i,v in ipairs(tab) do
      if is_function(v) then
        ret = v(s);
      else
        ret = v;
      end
    end
    return ret;
  end
end

function chooseuse_(tab)
  return function(s,p)
    return util.generic_choose(tab, function(s) return p == s end);
  end
end

function remove_(o,s)
  return function()
    remove(o,s);
  end
end

function event_(nm)
  return function()
    local o = ref_if(nm);
    o:enable();
  end
end

function unevent_(nm)
  return function()
    local o = ref_if(nm);
    o:disable();
  end
end